import { createContext, useContext, useReducer } from 'react';
import type { FC, ReactNode } from 'react';

// Action类型常量
const ACTIONS = {
  OPEN: 'OPEN',
  CLOSE: 'CLOSE',
  SET_DATA: 'SET_DATA',
} as const;

// State类型
export interface ModalState<T> {
  isVisible: boolean;
  data: T | null;
}

// Action类型
export type ModalAction<T> =
  | { type: typeof ACTIONS.OPEN; payload: T }
  | { type: typeof ACTIONS.CLOSE }
  | { type: typeof ACTIONS.SET_DATA; payload: T };

// Modal Actions类型
export interface ModalActions<T> {
  open: (data: T) => void;
  close: () => void;
  setData: (data: T) => void;
}

// Context类型
export interface ModalContextType<T> {
  state: ModalState<T>;
  actions: ModalActions<T>;
}

export function createModalContext<T = unknown>() {
  // Reducer
  const modalReducer = (state: ModalState<T>, action: ModalAction<T>): ModalState<T> => {
    switch (action.type) {
      case ACTIONS.OPEN:
        return {
          isVisible: true,
          data: action.payload,
        };
      case ACTIONS.CLOSE:
        return {
          isVisible: false,
          data: null,
        };
      case ACTIONS.SET_DATA:
        return {
          ...state,
          data: action.payload,
        };
      default:
        return state;
    }
  };

  // Context
  const Context = createContext<ModalContextType<T> | undefined>(undefined);

  // Provider组件
  const Provider: FC<{ children: ReactNode }> = ({ children }) => {
    const [state, dispatch] = useReducer(modalReducer, {
      isVisible: false,
      data: null,
    });

    // 封装dispatch方法
    const actions: ModalActions<T> = {
      open: (data: T) => dispatch({ type: ACTIONS.OPEN, payload: data }),
      close: () => dispatch({ type: ACTIONS.CLOSE }),
      setData: (data: T) => dispatch({ type: ACTIONS.SET_DATA, payload: data }),
    };

    return (
      <Context.Provider value={{ state, actions }}>
        {children}
      </Context.Provider>
    );
  };

  // Hook
  const useModal = () => {
    const context = useContext(Context);
    if (!context) {
      throw new Error('useModal must be used within its Provider');
    }
    const { state, actions } = context;
    return {
      isVisible: state.isVisible,
      data: state.data,
      actions
    };
  };

  return {
    Provider,
    useModal,
  };
}
